package com.test.crc;

import com.google.common.base.Strings;
import com.test.utils.NumberUtils;

public class Crc16Utils {

    private static Integer BINOMIAL = 0x8005; //0b11000000000000101 0x8005

    /**
     * 不准确，等待研究
     * 计算数字的CRC16值
     * 二项式：x^16+x^15+x^2+1 0b11000000000000101 0x8005
     * 1、校验第16位是否为1。
     * 1.1、第16位是1，如果为1则左移一位，正好为9位，跟二项式位数一样，做异或。
     * 1.2、第16位不是1，则左移一位，继续循环。
     * 此流程正好是模2除法取余的正向计算方式
     *
     * @return
     */
    public static Integer calcCrc(Integer num) {
        //        System.out.println(String.format("num=%s", num2Bin(num)));
        Integer crc = num;
        for (int i = 0; i < 8; i++) {
            if ((crc & 0x0001) != 0) {
                crc = (crc << 1) ^ BINOMIAL;
            } else {
                crc = crc << 1;
            }
//            String strCrc = num2Bin(crc);
//            System.out.println(String.format("times=%s, result=%s, num=%s, len=%s", i + 1, strCrc, crc, strCrc.length()));
        }
        return crc;
    }

    public static int CRC16_IBM(Integer num) {
        int wCRCin = 0x0000;
        int wCPoly = 0xa001;
        wCRCin = num ^ wCRCin;
        for (int j = 0; j < 8; j++) {
            if ((wCRCin & 0x0001) != 0) {
                wCRCin = wCRCin >> 1;
                wCRCin ^= wCPoly;
            } else {
                wCRCin = wCRCin >> 1;
            }
        }
        wCRCin = wCRCin ^ 0x0000;
        return wCRCin;
    }

    public static void generateCrc8Tabel() {
        StringBuilder sb = new StringBuilder();
        sb.append("private static int[] crc8Table = new int[]{\n");
        for (int i = 0; i < 256; i++) {
            int x = CRC16_IBM(i);
            String ss = "0x" + Strings.padStart(NumberUtils.num2Hex(x).toUpperCase(), 4, '0');
            sb.append(ss);
            if (i != 256 - 1) {
                sb.append(", ");
            }
            if ((i + 1) % 16 == 0) {
                sb.append("\n");
            }
        }
        sb.append("};");
        System.out.println(sb.toString());
    }

    public static void main(String[] args) {
//        generateCrc8Tabel();
        for (int i = 0; i < 257; i++) {
            System.out.println(0x0000 ^ i);
        }
    }
}
